package Task2;

import java.lang.reflect.Field;
public class ObjectMapper {
    /**
     * 对象转JSON字符串
     * @param obj
     * @return String JSON字符串
     */
    public static String toJSON(Object obj) {
        try {
            // 通过反射获取运行时Class对象的“类”
            Class objClass = obj.getClass();
            // 定义JSON字符串的内容
            StringBuilder json = new StringBuilder();
            // JSON对象开始
            json.append("{");
            // 遍历运行时Class对象的属性，利用反射
            // 获得属性名作为JSON对象的key，属性的值作为JSON对象的value
            // 这里只做基础数据类型的属性
            // 复杂数据类型(List,Map,Array)如何处理(多层结构嵌套处理)？
            // (1)成为大神 (2)使用第三方库 Jackson，GJson, FastJSON2
            Field[] fields = objClass.getDeclaredFields(); // 获得所有属性（包括私有属性)
            // objClass.getFields();// 获取所有public属性
            // fori - 对应数组
            // foreach - 对象集合，就是“迭代”
            for (int i = 0; i < fields.length; i++) {
                // 获取属性对象
                Field field = fields[i];
                // 破坏面向对象的封装特性，对私有属性进行访问？？？通常产生常说的“安全漏洞”
                field.setAccessible(true);
                // 设置JSON字符串的key
                json.append("\"").append(field.getName()).append("\" : ");
                // 设置JSON字符串的value，只处理基本数据类型
                // 判断是不是字符，字符串需要增加双引号
                if (field.getType() == String.class) {
                    json.append("\"").append(field.get(obj)).append("\"");
                }else{
                    json.append(field.get(obj));
                }
                //更富在需要拼接{} 和 [] 中的内容
                // JSON对象属性间分隔符，fileds对象最后一个属性不需要逗号
                if(i < fields.length - 1){
                    json.append(",");
                }
                
            }
            // JSON对象结束
            json.append("}");
            return json.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    // JSON字符串转对象
    // 要处理的对象类型未知，使用泛型
    public static <T> T fromJSON(String json, Class<T> clazz) {
        try{
            // 利用反射创建指定类的对象
            // T obj = clazz.getConstructor().newInstance();  // public构造方法 
            T obj = clazz.getDeclaredConstructor().newInstance(); // 可访问private构造方法
            // 从JSON字符串中获取所有的属性和对应的属性值
            // 去掉开始的大括号和最后的大括号后，使用逗号作为间隔符拆分字符串
            String[] keyValues = json.substring(1, json.length() - 1).split(",");
            // 遍历数组
            for (String keyValue : keyValues) {
                // 依据JSON格式分割key和value的键值对
                String[] pair = keyValue.split(":");
                //对于key，去掉前后双引号
                String fieldName = pair[0].trim().replace("\"", "");
                String fieldValue = pair[1].trim();
                // 获获取对象对应的属性值
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                // 设置属性值
                if(field.getType() == String.class){ //基础类型：字符串
                    // 去掉JSON字符串中的双引号
                    field.set(obj, fieldValue.replace("\"", ""));
                }else if(field.getType() == int.class){ //基础类型：整数
                    field.set(obj, Integer.parseInt(fieldValue));
                }else if(field.getType() == boolean.class){ //基础类型：布尔值
                    field.set(obj, Boolean.parseBoolean(fieldValue));
                }
            }
            return obj;
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }
}
